'''
Author: cw
Date: 2025-07-14
Description: ...
'''
import time
import hashlib

from sqlalchemy import select

from fapi import ServiceError

from models.mysql_model import Sessions
from models.data_model import Answer
from utils import db_util


async def create(
    appid: str,
    openid: str,
    test_id: int
):
    '''
    通过session_id 规则来限制session 有效期
    用户产生新的session时，历史session标记为删除(保证同一时间只能做一个测试)
    '''
    timestamp = int(time.time())
    five_minute_window = timestamp // 1800  # 1800秒 = 30分钟

    # 拼接 openid、时间窗口和密钥
    data_to_hash = f"{openid}-{test_id}.{five_minute_window}"

    # 使用 SHA-256 哈希算法生成 session_id
    hash_object = hashlib.sha256(data_to_hash.encode('utf-8'))
    session_id = hash_object.hexdigest()

    async with db_util.session_context() as session:
        # 清除历史session
        history_sessions = (await session.execute(
            select(Sessions).filter(
                Sessions.openid == openid,
                Sessions.appid == appid,
            )
        )).scalars()
        if history_sessions:
            for item in history_sessions:
                item.is_deleted = 1

        # 创建新的 session
        session.add(
            Sessions(
                session_id=session_id,
                appid=appid,
                openid=openid,
                test_id=test_id,
            )
        )
    return session_id


async def update(session_id: str, update_data: dict):
    """更新session"""
    async with db_util.session_context() as session:
        result = (await session.execute(
            select(Sessions).filter(
                Sessions.session_id == session_id,
                Sessions.is_deleted == 0
            )
        )).scalar()
        if not result:
            raise ServiceError('not find')
        for k, v in update_data.items():
            if hasattr(Sessions, k) and v is not None:
                setattr(result, k, v)
        await session.flush()
        return {'update': "OK"}


async def update_answer(session_id: str, answer: Answer):
    """更新session"""
    async with db_util.session_context() as session:
        result = (await session.execute(
            select(Sessions).filter(
                Sessions.session_id == session_id,
                Sessions.is_deleted == 0
            ).order_by(
                Sessions.id.desc()
            )
        )).scalar()
        if not result:
            raise ServiceError('not find')
        content = list(result.content or [])
        content.append(answer.model_dump())
        result.content = content
        await session.flush()
        return {'update': "ok"}


async def get(session_id: str):
    '''get info'''
    async with db_util.session_context() as session:
        result = (await session.execute(
            select(Sessions).filter(
                Sessions.session_id == session_id,
                Sessions.is_deleted == 0
            ).order_by(
                Sessions.id.desc()
            )
        )).scalar()
        if not result:
            raise ServiceError('not find')
        return result.to_dict()


async def soft_delete(session_id: str):
    '''软删除'''
    async with db_util.session_context() as session:
        # await session.execute(
        #     delete(Session).filter(Session.session_id == session_id)
        # )
        info = (await session.execute(
            select(Sessions).filter(
                Sessions.session_id == session_id,
                Sessions.is_deleted == 0
            ).order_by(Sessions.id.desc())
        )).scalar()
        if not info:
            raise ServiceError('not find')
        info.is_deleted = 1
        return {'delete': "ok"}


async def find_latest_session(openid: str) -> Sessions:
    """获取用户最新的session"""
    async with db_util.session_context() as session:
        info = (await session.execute(
            select(Sessions).filter(
                Sessions.openid == openid,
                Sessions.is_deleted == 0
            ).order_by(
                Sessions.id.desc()
            )
        )).scalar()
        return info
